<template>
  <div class="main-container">
    <div class="layout-container">
      <!-- 左侧操作区 -->
      <div class="left-section">
        <!-- PPT预览 -->
        <div class="preview-section">
          <div class="preview-container">
            <template v-if="isParsingFile">
              <div class="parsing-overlay">
                <a-spin size="large" />
                <span class="parsing-text">{{ parsingProgress }}</span>
              </div>
            </template>
            <template v-else>
              <template v-if="previewImages.length > 0">
                <img :src="previewImages[currentPageIndex]" alt="PPT预览" class="preview-image" />
              </template>
              <template v-else>
                <img :src="preview" alt="PPT预览" class="preview-image" />
              </template>
            </template>
          </div>
          <div class="page-navigation" v-if="!isParsingFile">
            <div class="navigation-content">
              <LeftOutlined class="nav-icon" :class="{ 'disabled': isDirectGenerating || isCustomGenerating }"
                @click="!(isDirectGenerating || isCustomGenerating) && (currentPageIndex = currentPageIndex === 0 ? pageCount - 1 : currentPageIndex - 1)" />
              <span>第 {{ currentPageIndex + 1 }} 页 / 共 {{ pageCount }} 页</span>
              <RightOutlined class="nav-icon" :class="{ 'disabled': isDirectGenerating || isCustomGenerating }"
                @click="!(isDirectGenerating || isCustomGenerating) && (currentPageIndex = currentPageIndex === pageCount - 1 ? 0 : currentPageIndex + 1)" />
            </div>
          </div>
        </div>
        <!-- 文本编辑区域 -->
        <div class="edit-section">
          <div class="edit-header">
            <span class="current-page">当前编辑: 第 {{ currentPageIndex + 1 }} 页 PPT</span>
            <a-button type="primary" size="small" class="save-button" @click="handleSave">
              <template #icon>
                <SaveOutlined class="save-icon" />
              </template>
              <span class="save-text">保存内容</span>
            </a-button>
          </div>
          <a-textarea v-model:value="slideText" :auto-size="{ minRows: 4, maxRows: 4 }" placeholder="请输入该页PPT的讲稿内容..."
            class="edit-textarea" :disabled="isDirectGenerating || isCustomGenerating" />
        </div>
      </div>
      <!-- 右侧操作区 -->
      <div class="right-section">
        <!-- 课件上传 -->
        <div class="upload-section">
          <div class="section-header">
            <h2 class="section-title">课件上传</h2>
            <a-tooltip title="支持PPT、PPTX格式，单个文件不超过50MB">
              <QuestionCircleOutlined class="help-icon" />
            </a-tooltip>
          </div>
          <div class="upload-area" @click="handleFileSelect" @dragover.prevent="handleDragOver"
            @dragleave.prevent="handleDragLeave" @drop.prevent="handleFileDrop">
            <div v-if="!hasUploadedFile" class="upload-content">
              <div class="upload-icon-wrapper">
                <FileTextOutlined class="upload-icon" />
              </div>
              <p class="upload-text">点击或拖拽文件至此处上传</p>
            </div>
            <div v-else class="file-info">
              <div class="file-info-header">
                <FileTextOutlined class="file-icon" />
                <span class="file-name">{{ fileInfo.name }}</span>
              </div>
              <div class="file-details">
                <span class="file-size">{{ fileInfo.size }}</span>
              </div>
              <a-button type="link" class="remove-file" @click.stop="handleRemoveFile">
                <DeleteOutlined />
              </a-button>
            </div>
            <input type="file" ref="fileInput" style="display: none" accept=".ppt,.pptx" @change="handleFileChange" />
          </div>
          <a-button type="primary" class="parse-button" :disabled="!hasUploadedFile" @click="handleParse">
            <template #icon>
              <FileSearchOutlined />
            </template>
            开始解析
          </a-button>
        </div>
        <!-- 导航栏 -->
        <a-tabs class="content-tabs">
          <a-tab-pane key="voice" tab="语音库">
            <!-- 语音库选择 -->
            <div class="voice-section">
              <div class="voice-library">
                <a-input-search v-model:value="searchText" :placeholder="searchPlaceholder" class="search-input" />
                <a-radio-group v-model:value="voiceTitleType" class="voice-type-selector">
                  <a-radio-button value="system" class="voice-type-button">系统声音</a-radio-button>
                  <a-radio-button value="clone" class="voice-type-button">克隆声音</a-radio-button>
                </a-radio-group>
                <div class="voice-list">
                  <div class="voice-grid">
                    <div v-for="voice in voices" :key="voice.id" :class="{'selected': selectedVoice === voice.id}"
                      class="voice-card" @click="selectVoice(voice.id)">
                      <div class="voice-card-header">
                        <span class="voice-name">{{ voice.voiceName }}</span>
                        <a-tag :color="voice.voiceType === 'system' ? 'blue' : 'green'">
                          {{ voice.voiceType === 'system' ? '系统' : '克隆' }}
                        </a-tag>
                      </div>
                      <div class="voice-card-footer">
                        <span
                          class="voice-description">{{ voice.voiceType === 'system' ? voice.shortDescription : voice.voiceNote }}</span>
                        <play-circle-outlined v-if="!isPreviewPlaying || currentPreviewId !== voice.id"
                          class="play-icon" @click.stop="playPreviewAudio(voice)" />
                        <pause-circle-outlined v-else class="play-icon" @click.stop="playPreviewAudio(voice)" />
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </a-tab-pane>
          <a-tab-pane key="video" tab="视频预览">
            <!-- 视频预览 -->
            <div class="video-card">
              <div class="video-preview">
                <h3 class="preview-title">视频导出</h3>
                <div class="video-container">
                  <video ref="videoPreview" class="video-player" controls :src="videoUrl"></video>
                </div>
                <div class="video-info">
                  <div class="info-text">
                    <!-- <div class="info-item">视频大小：{{ formatFileSize(videoSize) }}</div> -->
                    <div class="info-item">时长：{{ formatDuration(videoDuration) }}</div>
                  </div>
                  <a-button type="primary" class="download-button" @click="handleDownload">
                    <template #icon>
                      <DownloadOutlined />
                    </template>
                    下载视频
                  </a-button>
                </div>
              </div>
            </div>

          </a-tab-pane>
        </a-tabs>
        <!-- 生成控制 -->
        <div class="control-section">
          <div class="generate-buttons">
            <a-button type="primary" size="large" class="generate-button direct" @click="directGenerate"
              :loading="isDirectGenerating">
              <template #icon>
                <ThunderboltOutlined />
              </template>
              <span>直接生成</span>
            </a-button>
            <a-button type="primary" size="large" class="generate-button custom" @click="customGenerate"
              :loading="isCustomGenerating">
              <template #icon>
                <SettingOutlined />
              </template>
              <span>自定义生成</span>
            </a-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
  import { ref, onMounted, computed, watch, onUnmounted } from 'vue';
  import { message } from 'ant-design-vue';
  import {
    QuestionCircleOutlined,
    FileTextOutlined,
    SearchOutlined,
    PlayCircleOutlined,
    LeftOutlined,
    RightOutlined,
    SaveOutlined,
    DownloadOutlined,
    PauseCircleOutlined,
    ThunderboltOutlined,
    DeleteOutlined,
    SettingOutlined,
    FileSearchOutlined
  } from '@ant-design/icons-vue';
  import { getVoiceList } from '@/api/VoiceLibrary';
  import { previewPPT, generateVideo, customGenerateVideo, getDirectTaskStatus, getCustomTaskStatus } from '@/api/PPT';
  import preview from '@/assets/images/preview.webp';
  const previewAudioPlayer = ref(null);
  const isPreviewPlaying = ref(false);
  const currentPreviewId = ref(null);
  const hasUploadedFile = ref(false);
  const isParsingFile = ref(false);//是否正在解析文件
  const parsingProgress = ref('正在解析文件...');//文本内容
  const parsePercent = ref(0);
  const parseStatus = ref('active');
  //ppt预览器区部分
  const previewImages = ref([]);
  const currentPageIndex = ref(0);
  const pageCount = ref(1);
  const previewId = ref('');
  // 处理文件解析
  const handleParse = async () => {
    isParsingFile.value = true;
    currentPageIndex.value = 0;
    parsingProgress.value = '正在解析文件...';
    try {
      // 直接传递文件对象
      const res = await previewPPT(uploadedFile.value);
      pageCount.value = res.data.pageCount;
      previewId.value = res.data.previewId;
      previewImages.value = res.data.pages.map(page => page.imageUrl);
      isParsingFile.value = false;
      console.log(res);
    } catch (error) {
      console.error('文件解析失败:', error);
      message.error('文件解析失败',1);
      parsingProgress.value = '解析失败';
      isParsingFile.value = false;
    }
  };
  //语音库部分
  const voices = ref([]);
  const searchText = ref('');
  // 音色选择
  const selectedVoice = ref(); // 默认选中系统声音的第一个
  const selectVoice = (voiceId) => {
    selectedVoice.value = voiceId;
  };

  // 音色类型选择
  const voiceTitleType = ref('system');
  // 获取声音列表数据
  const fetchVoiceList = async (type = voiceTitleType.value, keyword = searchText.value) => {
    try {
      const res = await getVoiceList({ type, keyword });
      voices.value = res.data.list;
    } catch (error) {
      console.error('获取声音列表失败:', error);
    }
  };
  // 在组件挂载时获取数据
  onMounted(async () => {
    await fetchVoiceList();
  });
  // 监听搜索关键字和声音类型变化
  watch([searchText, voiceTitleType], async ([newKeyword, newType]) => {
    await fetchVoiceList(newType, newKeyword);
  });
  // 搜索相关
  const searchPlaceholder = computed(() => {
    return voiceTitleType.value === 'system' ? '搜索系统声音' : '搜索克隆声音';
  });
  // 播放预览音频
  const playPreviewAudio = async (voice) => {
    try {
      console.log(voice);

      if (!voice.outputUrl) {
        message.warning('音频文件不存在',1);
        return;
      }

      // 如果当前正在播放这个音频，切换播放状态
      if (currentPreviewId.value === voice.id) {
        if (isPreviewPlaying.value) {
          previewAudioPlayer.value.pause();
          isPreviewPlaying.value = false;
          currentPreviewId.value = null;
          return;
        }
      } else {
        // 如果要播放新的音频，先停止当前播放
        if (previewAudioPlayer.value) {
          previewAudioPlayer.value.pause();
          isPreviewPlaying.value = false;
          currentPreviewId.value = null;
        }
      }

      // 初始化音频播放器
      if (!previewAudioPlayer.value) {
        previewAudioPlayer.value = new Audio();
        previewAudioPlayer.value.addEventListener('ended', () => {
          isPreviewPlaying.value = false;
          currentPreviewId.value = null;
        });
      }

      // 设置新的音频源并播放
      previewAudioPlayer.value.src = voice.outputUrl;
      await previewAudioPlayer.value.play();

      // 更新播放状态
      isPreviewPlaying.value = true;
      currentPreviewId.value = voice.id;
    } catch (error) {
      console.error('播放预览音频失败:', error);
      message.error('播放音频失败',1);
      isPreviewPlaying.value = false;
      currentPreviewId.value = null;
    }
  };

  // 组件卸载时清理音频播放器
  onUnmounted(() => {
    if (previewAudioPlayer.value) {
      previewAudioPlayer.value.pause();
      previewAudioPlayer.value = null;
    }
  });

  // 文本编辑部分
  const previewImage = ref(preview);
  const slideText = ref('');
  // 添加一个数组来存储所有页面的文本
  const slidesText = ref([]);

  // 监听页面切换，加载对应页面的文本
  watch(currentPageIndex, (newIndex) => {
    // 加载新页面的文本
    slideText.value = slidesText.value[newIndex] || '';
  });

  // 保存当前页文本
  const handleSave = () => {
    slidesText.value[currentPageIndex.value] = slideText.value;
    message.success('保存成功',1);
  };
  //上传文件部分
  // 文件上传相关的响应式变量
  const fileInput = ref(null);          // 文件输入框的引用
  const uploadedFile = ref(null);       // 已上传的文件对象
  const fileInfo = ref({               // 文件信息对象
    name: '',                          // 文件名
    size: 0                           // 文件大小
  });

  // 处理点击上传区域时的文件选择
  const handleFileSelect = () => {
    fileInput.value.click();
  };

  // 处理文件选择变化事件
  const handleFileChange = (event) => {
    const file = event.target.files[0];
    if (file) {
      validateAndProcessFile(file);    // 验证并处理选择的文件
    }
  };

  // 处理文件拖拽悬停事件
  const handleDragOver = (event) => {
    event.preventDefault();
    const uploadArea = event.currentTarget;
    // 更新上传区域的视觉样式
    uploadArea.style.borderColor = '#60a5fa';
    uploadArea.style.borderStyle = 'solid';
    uploadArea.style.backgroundColor = 'rgba(96, 165, 250, 0.05)';
  };

  // 处理文件拖拽离开事件
  const handleDragLeave = (event) => {
    event.preventDefault();
    const uploadArea = event.currentTarget;
    // 恢复上传区域的默认样式
    uploadArea.style.borderColor = '#e5e7eb';
    uploadArea.style.borderStyle = 'dashed';
    uploadArea.style.backgroundColor = 'transparent';
  };

  // 处理文件拖放事件
  const handleFileDrop = (event) => {
    event.preventDefault();
    const uploadArea = event.currentTarget;
    // 恢复上传区域的默认样式
    uploadArea.style.borderColor = '#e5e7eb';
    uploadArea.style.borderStyle = 'dashed';
    uploadArea.style.backgroundColor = 'transparent';

    const file = event.dataTransfer.files[0];
    if (file) {
      validateAndProcessFile(file);    // 验证并处理拖放的文件
    }
  };

  // 验证和处理上传的文件
  const validateAndProcessFile = (file) => {
    // 定义允许的文件类型和大小限制
    const validTypes = ['application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'];
    const maxSize = 50 * 1024 * 1024; // 100MB

    // 验证文件类型
    if (!validTypes.includes(file.type)) {
      message.error('请上传PPT或PPTX格式的文件',1);
      return;
    }

    // 验证文件大小
    if (file.size > maxSize) {
      message.error('文件大小不能超过50MB',1);
      return;
    }

    // 文件验证通过，更新状态
    uploadedFile.value = file;
    fileInfo.value = {
      name: file.name,
      size: formatFileSize(file.size),
    };
    hasUploadedFile.value = true;
    message.success('文件上传成功',1);
  };

  // 处理移除已上传文件
  const handleRemoveFile = (event) => {
    event.stopPropagation();           // 阻止事件冒泡
    // 重置所有文件相关的状态
    uploadedFile.value = null;
    fileInfo.value = {
      name: '',
      size: 0
    };
    hasUploadedFile.value = false;
    fileInput.value.value = '';         // 清空文件输入框
    message.success('文件已移除',1);
  };

  //视频预览部分
  const videoUrl = ref('');  // 视频预览的URL
  const videoDuration = ref(0);  // 视频时长，默认3分钟
  // const videoSize = ref(15728640);  // 视频文件大小，默认15MB


  // 格式化文件大小的工具函数
  // 将字节数转换为可读的文件大小格式（B、KB、MB、GB）
  const formatFileSize = (bytes) => {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
  };

  // 格式化视频时长的工具函数
  // 将秒数转换为 分:秒 格式
  const formatDuration = (seconds) => {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = seconds % 60;
    return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
  };

  // 处理视频下载
  // 创建一个临时的<a>标签来触发文件下载
  const handleDownload = () => {
    const link = document.createElement('a');
    link.href = videoUrl.value;
    link.download = '演示视频.mp4';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };
  // 生成视频部分
  const isDirectGenerating = ref(false);
  const isCustomGenerating = ref(false);

  // 直接生成视频
  const directGenerate = async () => {
    if (!uploadedFile.value) {
      message.warning('请先上传PPT文件',1);
      return;
    }
    if (!previewId.value) {
      message.warning('请先解析PPT文件',1);
      return;
    }
    if (!selectedVoice.value) {
      message.warning('请先选择一个声音',1);
      return;
    }
      message.loading('正在生成视频，请稍候...', 0);
    try {
      isDirectGenerating.value = true;
      const res = await generateVideo({
        voiceId: selectedVoice.value,
        previewId: previewId.value
      });
      const taskId = res.data.taskId;
      // 轮询检查任务状态
      const timer = setInterval(async () => {
        try {
          const statusRes = await getDirectTaskStatus(taskId);
          console.log(statusRes);
          const progress = statusRes.data.progress;
          if (progress >= 100) {
            clearInterval(timer);
            isDirectGenerating.value = false;
            // // 更新视频预览
            videoUrl.value = statusRes.data.outputUrl;
            videoDuration.value = Math.floor(statusRes.data.duration / 1000); // 将毫秒转换为秒
            message.destroy();
            message.success('视频生成成功',1);
          }
        } catch (error) {
          clearInterval(timer);
          isDirectGenerating.value = false;
          message.destroy();
          message.error('获取任务状态失败',1);
          console.error('获取任务状态失败:', error);
        }
      }, 2000);
    } catch (error) {
      isDirectGenerating.value = false;
      message.destroy();
      message.error('生成视频失败',1);
      console.error('生成视频失败:', error);
    }
  };

  // 自定义生成视频
  const customGenerate = async () => {
    if (!uploadedFile.value) {
      message.warning('请先上传PPT文件',1);
      return;
    }
    if (!previewId.value) {
      message.warning('请先解析PPT文件',1);
      return;
    }
    if (!selectedVoice.value) {
      message.warning('请先选择一个声音',1);
      return;
    }
    message.loading('正在生成视频，请稍候...', 0);
    try {
      isCustomGenerating.value = true;
      const res = await customGenerateVideo({
        voiceId: selectedVoice.value,
        previewId: previewId.value,
        texts: slidesText.value
      });
      const taskId = res.data.taskId;
      // 轮询检查任务状态
      const timer = setInterval(async () => {
        try {
          const statusRes = await getCustomTaskStatus(taskId);
          const progress = statusRes.data.progress;
          console.log(statusRes);
          if (progress >= 100) {
            clearInterval(timer);
            isCustomGenerating.value = false;
            // 更新视频预览
            videoUrl.value = statusRes.data.outputUrl;
            videoDuration.value = Math.floor(statusRes.data.duration / 1000); // 将毫秒转换为秒
            message.destroy();
            message.success('视频生成成功',1);
          }
        } catch (error) {
          clearInterval(timer);
          isCustomGenerating.value = false;
          message.destroy();
          message.error('获取任务状态失败',1);
          console.error('获取任务状态失败:', error);
        }
      }, 2000);
    } catch (error) {
      isCustomGenerating.value = false;
      message.destroy();
      message.error('生成视频失败',1);
      console.error('生成视频失败:', error);
    }
  };
</script>

<style lang="scss" scoped>
  .main-container {
    background-color: #f3f4f6;

    .layout-container {
      display: flex;
      height: 90vh;
      margin: 0 auto;
      max-width: 88rem;

      .left-section {
        flex: 1;
        display: flex;
        flex-direction: column;

        .preview-section {
          flex: 0.96;
          background-color: #e3e4e7;
          padding: 1.5rem;
          position: relative;

          .preview-container {
            background-color: white;
            border-radius: 0.5rem;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;

            .preview-image {
              max-width: 95%;
              max-height: 90%;
              object-fit: contain;
              margin-bottom: 2rem;
            }

            .parsing-overlay {
              position: absolute;
              top: 0;
              left: 0;
              right: 0;
              bottom: 0;
              display: flex;
              flex-direction: column;
              align-items: center;
              justify-content: center;
              gap: 1rem;

              .parsing-text {
                color: #4b5563;
                font-size: 1rem;
                margin-top: 1rem;
              }
            }
          }

          .page-navigation {
            position: absolute;
            bottom: 2rem;
            left: 50%;
            transform: translateX(-50%);
            background-color: white;
            border-radius: 9999px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            padding: 0.2rem 1rem;
            width: 260px;

            .navigation-content {
              display: flex;
              align-items: center;
              justify-content: space-between;
              width: 100%;
              padding: 0 0.5rem;

              .nav-icon {
                cursor: pointer;
                font-size: 1.2em;
                padding: 8px;
                color: #4b5563;
                transition: all 0.3s ease;
                display: flex;
                align-items: center;
                justify-content: center;

                &.disabled {
                  cursor: not-allowed;
                  opacity: 0.5;
                  pointer-events: none;
                }

                &:hover:not(.disabled) {
                  transform: scale(1.15);
                  color: #1890ff;
                }

                &:active:not(.disabled) {
                  transform: scale(0.95);
                }
              }
            }
          }
        }

        .edit-section {
          height: 180px;
          background-color: white;
          border-top: 1px solid #e5e7eb;
          padding: 1rem;
          display: flex;
          flex-direction: column;

          .edit-header {
            position: relative;
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 1.2rem;

            .current-page {
              color: #4b5563;
            }

            .save-button {
              position: absolute;
              right: 5px;
              top: 50%;
              transform: translateY(-50%);
              height: calc(1 * 32px);
              border-radius: 0.5rem;
              transition: all 0.3s ease;
              display: flex;
              align-items: center;
              /* gap: 0.5rem; */
              border: none;
              color: white;

              &:hover {
                transform: translateY(-50%) scale(1.05);
                box-shadow: 0 2px 8px rgba(74, 144, 226, 0.3);
              }

              .save-icon {
                font-size: 16px;
              }

              .save-text {
                font-weight: 400;
              }
            }
          }

          .edit-textarea {
            border-radius: 0.375rem;
            padding: 0.5rem;
          }
        }
      }

      .right-section {
        width: 480px;
        height: 97%;
        /* max-height: ; */
        border-left: 1px solid #e5e7eb;
        background-color: white;
        padding: 1rem;
        display: flex;
        flex-direction: column;

        :deep(.content-tabs) {
          .ant-tabs-nav {
            width: 100%;

            .ant-tabs-nav-list {
              width: 70%;
              margin: 0 auto;
              justify-content: space-around;

              .ant-tabs-tab {
                flex: 1;
                display: flex;
                justify-content: center;
              }

              .ant-tabs-ink-bar {
                width: 50% !important;
              }
            }
          }
        }

        .upload-section {
          margin-bottom: 0.5rem;

          .section-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 0.75rem;

            .section-title {
              font-size: 1.125rem;
              font-weight: 500;
            }

            .help-icon {
              color: #9ca3af;
              cursor: pointer;
            }
          }

          .parse-button {
            width: 100%;
            margin-top: 1rem;
            height: 40px;
            font-size: 1rem;
            font-weight: 500;
            border-radius: 0.5rem;
            transition: all 0.2s;

            &:hover:not(:disabled) {
              transform: scale(1.02);
              box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            }

            &:disabled {
              cursor: not-allowed;
              opacity: 0.6;
            }
          }
        }

        .upload-area {
          border: 2px dashed #e5e7eb;
          border-radius: 0.5rem;
          height: 120px;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          transition: all 0.3s;

          &:hover {
            border-color: #60a5fa;
            border-style: solid;
            background-color: rgba(96, 165, 250, 0.05);
          }

          .upload-content {
            text-align: center;

            .upload-icon-wrapper {
              width: 3rem;
              height: 3rem;
              margin: 0 auto 0.5rem;
              color: #9ca3af;
              display: flex;
              align-items: center;
              justify-content: center;

              .upload-icon {
                font-size: 2rem;
              }
            }

            .upload-text {
              color: #6b7280;
            }
          }

          .file-info {
            width: 100%;
            padding: 1.25rem;
            position: relative;
            border-radius: 0.5rem;
            transition: all 0.2s ease;

            .file-info-header {
              display: flex;
              align-items: center;
              margin-bottom: 0.75rem;

              .file-icon {
                font-size: 1.75rem;
                color: #4A90E2;
                margin-right: 0.75rem;
                transition: transform 0.2s ease;

                &:hover {
                  transform: scale(1.1);
                }
              }

              .file-name {
                font-size: 1.125rem;
                color: #1f2937;
                font-weight: 500;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                max-width: calc(100% - 6rem);
                letter-spacing: -0.01em;
              }
            }

            .file-details {
              display: flex;
              align-items: center;
              gap: 1rem;
              color: #64748b;
              font-size: 0.875rem;
              padding-left: 0.25rem;

              .file-size {
                display: flex;
                align-items: center;
                gap: 0.25rem;

                &::before {
                  content: "•";
                  color: #94a3b8;
                }
              }
            }

            .remove-file {
              position: absolute;
              right: 1rem;
              top: 50%;
              transform: translateY(-50%);
              color: #9ca3af;
              transition: all 0.2s ease;
              font-size: 1.5em;
              display: flex;
              align-items: center;
              justify-content: center;

              &:hover {
                color: #ef4444;
                transform: translateY(-50%) scale(1.1);
              }
            }
          }
        }

        .voice-section {
          margin-bottom: 1.5rem;

          .voice-library {
            /* margin-top: 23px; */
            height: 380px;
            background-color: white;
            border-radius: 0.5rem;

            /* padding: 1rem; */
            .search-input {
              margin-bottom: 1rem;

              .search-icon {
                color: #9ca3af;
              }
            }

            .voice-type-selector {
              margin-bottom: 1rem;
              width: 100%;
              border: 1px solid #e5e7eb;
              border-radius: 0.5rem;

              .voice-type-button {
                width: 50%;
                text-align: center;
              }
            }

            .voice-list {
              height: 280px;
              overflow-y: auto;
              padding-right: 0.5rem;

              /* 自定义滚动条样式 */
              &::-webkit-scrollbar {
                width: 6px;
              }

              &::-webkit-scrollbar-track {
                background: #e5e5e5;
                border-radius: 3px;
              }

              &::-webkit-scrollbar-thumb {
                background: #e5e5e5;
                border-radius: 3px;

                &:hover {
                  background: #b2b2b2;
                }
              }

              .voice-grid {
                display: grid;
                grid-template-columns: repeat(2, 1fr);
                gap: 1rem;

                .voice-card {
                  background-color: white;
                  border-radius: 0.5rem;
                  padding: 0.75rem 0 0.75rem 0.5rem;
                  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
                  display: flex;
                  flex-direction: column;
                  border: 2px solid #e5e7eb;
                  transition: border-color 0.3s ease;

                  &:hover {
                    border-color: #4897f8;
                  }

                  &.selected {
                    border-color: #4897f8;
                  }

                  .voice-card-header {

                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    margin-bottom: 0.5rem;

                    .voice-name {
                      font-weight: 500;
                      color: #1f2937;
                    }
                  }

                  .voice-card-footer {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;

                    .voice-description {
                      color: #6b7280;
                      font-size: 0.875rem;
                    }

                    .play-icon {
                      margin-right: 15px;
                      color: #2563eb;
                      font-size: 1.25rem;
                      cursor: pointer;

                      &:hover {
                        color: #1d4ed8;
                      }
                    }
                  }
                }
              }
            }
          }
        }

        .video-card {
          margin-top: auto;
          padding-top: 1rem;
          border-top: 1px solid #e5e7eb;
          margin-bottom: 4.66rem;

          .video-preview {
            background-color: #f9fafb;
            border-radius: 0.5rem;
            padding: 1rem;
            margin-bottom: 1rem;

            .preview-title {
              font-size: 1rem;
              font-weight: 500;
              margin-bottom: 0.75rem;
            }

            .video-container {
              background-color: #000;
              border-radius: 0.375rem;
              overflow: hidden;
              margin-bottom: 0.75rem;

              .video-player {
                width: 100%;
                height: 200px;
                object-fit: contain;
              }
            }

            .video-info {
              display: flex;
              justify-content: space-between;
              align-items: center;

              .info-text {
                .info-item {
                  color: #6b7280;
                  font-size: 0.875rem;
                  margin-bottom: 0.25rem;

                  &:last-child {
                    margin-bottom: 0;
                  }
                }
              }

              .download-button {
                border-radius: 0.375rem;
                transition: all 0.2s;

                &:hover {
                  transform: scale(1.05);
                  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
                }
              }
            }
          }
        }

        .control-section {
          /* margin-top: auto; */
          /* margin-top: 2rem; */
          padding-top: 1rem;
          border-top: 2px solid #e5e7eb;

          .generate-buttons {
            display: flex;
            gap: 1rem;
            margin-bottom: 0.5rem;

            .generate-button {
              flex: 1;
              height: 48px;
              display: flex;
              align-items: center;
              justify-content: center;
              gap: 0.5rem;
              border-radius: 0.5rem;
              transition: all 0.3s ease;
              font-weight: 500;

              &:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
              }

              &:active {
                transform: translateY(0);
              }

              .anticon {
                font-size: 1.2em;
              }
            }
          }
        }
      }
    }
  }
</style>